#include<spdlog/spdlog.h>
#include<spdlog/sinks/basic_file_sink.h>
#include<spdlog/sinks/rotating_file_sink.h>
#include<spdlog/sinks/daily_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/async.h>

int main()
{
    // 设置日志格式
    spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [thread %t] %v");
    spdlog::info("Hello World");
}

//异步日志
int main7()
{
    // 初始化异步日志
    //初始化全局线程池
    spdlog::init_thread_pool(8192, 1);  // 队列大小8192，1个线程

    auto async_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/async_log.txt");
    auto async_logger = std::make_shared<spdlog::async_logger>(
        "async_logger",
        async_sink,
        spdlog::thread_pool(),
        spdlog::async_overflow_policy::block //队列满时阻塞主线程，保证不丢日志
    );
    //主线程仅把日志 push 进队列 立即返回，不直接写盘；真正刷盘由后台线程稍后完成。
      async_logger->info("This is logged asynchronously,{}");
    //把 logger 注册到 spdlog 全局表，后续可用spdlog::get("async_logger")->info(...) 直接调用。
    spdlog::register_logger(async_logger);
    return 0;
}

//同时输出到控制台和文件
int main6()
{
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
    auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/multi_sink.txt", true);

    //日志落地方式数组
    std::vector<spdlog::sink_ptr> sinks {console_sink, file_sink};
    //内部有个sinkPtr的数组，即落地方式数组
    auto logger = std::make_shared<spdlog::logger>("multi_sink", sinks.begin(), sinks.end());
    logger->info("This appears in both console and file");
    return 0;
}

//spdlog::daily_logger_mt(
//     const std::string& logger_name,        // 日志器名字
//     const std::string& filename,           // 基础路径，支持占位符
//     int hour = 0,                          // 每天几点触发轮转（0–23）
//     int minute = 0,                        // 每天几分触发轮转（0–59）
//     bool truncate = false,                 // 若文件已存在是否清空
//     uint16_t max_files = 0                 // 保留最近多少个日志文件，0=不删除
// );
//按照日期分割
int main5()
{
    // 每天 20:18 切分，保留最近 30 个文件
    auto logger = spdlog::daily_logger_mt(
        "daily_2018",                 // logger 名字
        "logs/app.log",   // 文件名带日期
        20,                           // hour = 20
        20,                           // minute = 18
        false,                        // 不截断
        30                            // 最多保留 30 个旧文件
    );

    spdlog::set_default_logger(logger);
    spdlog::set_level(spdlog::level::info);

    // 随便写几条日志，观察 20:18 是否生成新文件
    while (true) {
        spdlog::info("hello, now is {:%Y-%m-%d %H:%M:%S}", std::chrono::system_clock::now());
        std::this_thread::sleep_for(std::chrono::seconds(10));
    }
    return 0;
}



//按大小分割日志文件
int main4()
{
    auto rotating_logger = spdlog::rotating_logger_mt(
        "size_logger",
        "logs/rotating.txt",
        1024*1024*5,3);
        //最大5MB 保留三个文件
        //max_files = 3 表示：除了当前正在写的文件外，最多再保留 3 个旧文件。
    int count = 0;
    while(count < 1024*1024*30)
        rotating_logger->info("hello world {}",count++);

    return 0;
}

//基本文件日志
int main3()
{
    //basic_logger_mt 是 spdlog 提供的专门把日志写入文件的日志器。
    auto logger = spdlog::basic_logger_mt("file_logger", "./logs/mylog.txt");
    logger->info("This message goes to file");
    
    //设置file_logger为默认的日志器,往后不用logger->info直接spdlog::info
    spdlog::set_default_logger(logger);
    spdlog::info("Now this also goes to file");
    return 0;
}

//最小日志级别设置
int main2()
{
    spdlog::set_level(spdlog::level::debug);  // 设置全局日志级别 最小日志级别设为 debug。

    // 不同级别的日志
    spdlog::trace("Trace message");           // 最详细
    spdlog::debug("Debug message");           // 调试信息
    spdlog::info("Info message");             // 一般信息
    spdlog::warn("Warning message");          // 警告
    spdlog::error("Error message");           // 错误
    spdlog::critical("Critical message");     // 严重错误
    return 0;
}


//简单的控制台不同等级日志
int main1()
{
    spdlog::info("Hello,{:>10}!","world");//右对齐宽10
    spdlog::warn("This is a warning");
    spdlog::error("Error code: {1} {0}",404,499); // 499 404
    spdlog::error("Error code: {:0>6}",404); // 000404
    spdlog::critical("Critical Error");
    return 0;
}